#include "Sprite.h"
#include "Engine.h"

extern VGPLib vgplib;
using namespace std;


Sprite::Sprite()
{
}

Sprite::~Sprite()
{
	SAFE_DEL(modules);
	SAFE_DEL(frames);
	SAFE_DEL(anims);
}

//-------------------------------------------------
//Paint module with: moduleId, x, y, flag, scale
//-------------------------------------------------
void Sprite::PaintModule ( int moduleID, int _x, int _y, int flag , int scale)
{
	int x, y, w, h, sw, sh;
	x = modules[moduleID].x;
	y = modules[moduleID].y;
	w = sw = modules[moduleID].w;
	h = sh = modules[moduleID].h;
	if ( scale != 100 ) //for scale
	{
		sw= sw*scale/100;
		sh= sh*scale/100;
	}
	VGPLib::GetVGPLib()->PaintImage( x, y, w, h, _x, _y, sw, sh, flag, imageID, width, height );
}

void Sprite::PaintModule ( int moduleID, int _x, int _y, int flag )
{
	PaintModule ( moduleID, _x, _y, flag , 100 );
}

//-------------------------------------------------
//Paint Fmodule with: frameID, moduleID, x, y, flag, scale
//-------------------------------------------------
void Sprite::PaintFModule (int frameID, int moduleID, int _x, int _y, int scale)
{
	int x, y;
	x = frames[frameID].fmodule[moduleID].x + _x;
	y = frames[frameID].fmodule[moduleID].y + _y;
	PaintModule( frames[frameID].fmodule[moduleID].FM_ID, x, y, frames[frameID].fmodule[moduleID].flag, scale);
}

void Sprite::PaintFModule (int frameID, int moduleID, int _x, int _y)
{
	PaintFModule (frameID, moduleID, _x, _y, 100 );
}

//-------------------------------------------------
//Paint Frame with: frameID, x, y, flag, scale
//-------------------------------------------------
void Sprite::PaintFrame ( int frameID, int _x, int _y, int scale )
{
	int count = 0;
	int Xmin, Ymin, Xmax, Ymax;	
	Xmin = Ymin = Xmax = Ymax = 0;

	if ( scale != 100 )
	{
		while ( frames[frameID].fmodule[count].FM_ID >= 0 )
		{		
			//Find min X
			if ( Xmin > frames[frameID].fmodule[count].x )
				Xmin = frames[frameID].fmodule[count].x; 
			//Find min y
			if ( Ymin > frames[frameID].fmodule[count].y )
				Ymin = frames[frameID].fmodule[count].y; 

			//Find max X, Y
			if ( ( frames[frameID].fmodule[count].flag & VGPLib::FREE_ROT ) != 0 ) //has rotation 90
			{
				if ( Xmax < ( frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].h ) )
					Xmax =  frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].h;

				if ( Ymax < ( frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].w ) )
					Ymax =  frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].w;
			}
			else
			{
				if ( Xmax < ( frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].w ) )
					Xmax =  frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].w;

				if ( Ymax < ( frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].h ) )
					Ymax =  frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].h;
			}
			count++;
		}
	}

	int scaleW, scaleH;
	scaleW = (Xmax - Xmin)*(scale - 100)/100;
	scaleH = (Ymax - Ymin)*(scale - 100)/100;
	_x -= scaleW/2;
	_y -= scaleH/2;

	count = 0;
	while ( frames[frameID].fmodule[count].FM_ID >= 0 )
	{		
		int scaleX = 0, scaleY = 0;
		if ( scale != 100 )
		{
			scaleX = (frames[frameID].fmodule[count].x - Xmin)*(scale - 100)/100;
			scaleY = (frames[frameID].fmodule[count].y - Ymin)*(scale - 100)/100;
		}
		PaintFModule ( frameID, count, scaleX + _x , scaleY + _y, scale );	
		count++;
	}
		
}

void Sprite::PaintFrame ( int frameID, int _x, int _y )
{
	int count = 0;
	while ( frames[frameID].fmodule[count].FM_ID >= 0 )
	{		
		PaintFModule ( frameID, count, _x , _y, 100 );	
		count++;
	}
}

//-------------------------------------------------
//Paint AFrame with: animID, frameID, x, y, flag, scale
//-------------------------------------------------
void Sprite::PaintAFrame ( int animID, int frameID, int _x, int _y, int scale )
{
	int x, y;
	x = anims[animID].aframe[frameID].x + _x;
	y = anims[animID].aframe[frameID].y + _y;
	PaintFrame( anims[animID].aframe[frameID].AF_ID, x, y, scale);
}

void Sprite::PaintAFrame ( int animID, int frameID, int _x, int _y )
{
	PaintAFrame ( animID, frameID, _x, _y, 100 );
}

//Get num of module of a frame
int Sprite::GetFModules ( int frameID )
{
	int count = 0;
	while ( frames->fmodule[count].FM_ID >= 0 )
		count++;

	return count;
}


//Get num of frame of a anim
int Sprite::GetAFrames ( int animID )
{
	int count = 0;
	while ( anims->aframe[count].AF_ID >= 0 )
		count++;

	return count;
}

//Get a frame rect
Module Sprite::GetFrameRect ( int frameID )
{
	Module rect;
	if ( frames[frameID].rect[0].w == -1 && frames[frameID].rect[0].h == -1 )
	{
		int Xmin, Ymin, Xmax, Ymax, count;	
		Xmin = Ymin = Xmax = Ymax = count = 0;

		while ( frames[frameID].fmodule[count].FM_ID >= 0 )
		{		
			//Find min X
			if ( Xmin > frames[frameID].fmodule[count].x )
				Xmin = frames[frameID].fmodule[count].x; 
			//Find min y
			if ( Ymin > frames[frameID].fmodule[count].y )
				Ymin = frames[frameID].fmodule[count].y; 

			//Find max X, Y
			if ( ( frames[frameID].fmodule[count].flag & VGPLib::FREE_ROT ) != 0 ) //has rotation 90
			{
				if ( Xmax < ( frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].h ) )
					Xmax =  frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].h;

				if ( Ymax < ( frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].w ) )
					Ymax =  frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].w;
			}
			else
			{
				if ( Xmax < ( frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].w ) )
					Xmax =  frames[frameID].fmodule[count].x + modules[frames[frameID].fmodule[count].FM_ID].w;

				if ( Ymax < ( frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].h ) )
					Ymax =  frames[frameID].fmodule[count].y + modules[frames[frameID].fmodule[count].FM_ID].h;
			}
			count++;
		}

		rect.x = Xmin;
		rect.y = Ymin;
		rect.w = Xmax - Xmin;
		rect.h = Ymax - Ymin;	
	}
	else
	{
		rect.x = frames[frameID].rect[0].x;
		rect.y = frames[frameID].rect[0].y;
		rect.w = frames[frameID].rect[0].w;
		rect.h = frames[frameID].rect[0].h;
	}

	return rect;
	
}

//Get list frame rect
Module* Sprite::GetFrameRects ( int frameID )
{
	if ( frames[frameID].rect[0].w == -1 && frames[frameID].rect[0].h == -1 )
	{
		Module temp = GetFrameRect ( frameID );
		Module* _rect = new Module[2];		
		_rect[0].x = temp.x;
		_rect[0].y = temp.y;
		_rect[0].w = temp.h;
		_rect[0].h = temp.h;
		_rect[1].x = _rect[1].y = _rect[1].w = _rect[1].h = -1;
		return _rect;
	}

	return frames[frameID].rect;
}


//set font mapping
void Sprite::SetFontMapping ( int mapping[] )
{
	for (int i = 0; i < 256; i++ )
		fontMapping[i] = mapping[i];
}

//draw a char
void Sprite::DrawChar ( char ch, int x, int y )
{
	PaintFrame (fontMapping[ch], x, y);
}

//draw string
void Sprite::DrawString (char* str, int _x, int _y, int anchor )
{
	int x, y, str_W, strH;
	x = _x;
	y = _y;
	str_W = strH = 0;

	//calucate string width and height
	if ( anchor != VGPLib::TOP | VGPLib::LEFT )
	{
		for (int i = 0; i < strlen( str ); i++ )
		{
			str_W += modules[frames[fontMapping[str[i]]].fmodule[0].FM_ID].w + 2;
		}
	}


	if ( anchor == ( VGPLib::TOP | VGPLib::LEFT ) )
	{
		x = _x;
		y = _y;
	}
	else if ( anchor == ( VGPLib::TOP | VGPLib::RIGHT ) )
	{
		x -= str_W;
	}
	else if ( anchor == ( VGPLib::TOP | VGPLib::CENTER ) )
	{
		x -= str_W/2;
	}
	else if ( anchor == ( VGPLib::CENTER | VGPLib::CENTER ) )
	{
		x -= str_W/2;
		y += modules[frames[fontMapping['a']].fmodule[0].FM_ID].w/2;
	}
	else
	{
		x = _x;
		y = _y;
	}
	
	
	for (int i = 0; i < strlen( str ); i++ )
	{
		DrawChar( str[i], x, y );
		x += modules[frames[fontMapping[str[i]]].fmodule[0].FM_ID].w + 2; //2 mean 2 pixel before and after of char
	}
}

void Sprite::DrawString (char* str, int _x, int _y)
{
	DrawString ( str, _x, _y, VGPLib::TOP | VGPLib::LEFT );
}
